package org.lld.im.service.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lld.im.codec.pack.user.UserCustomStatusChangeNotifyPack;
import com.lld.im.codec.pack.user.UserStatusChangeNotifyPack;
import org.apache.commons.lang3.StringUtils;
import org.lld.im.common.constant.Constants;
import org.lld.im.common.enums.command.UserEventCommand;
import org.lld.im.common.model.ClientInfo;
import org.lld.im.common.model.UserSession;
import org.lld.im.service.friendship.service.ImFriendShipService;
import org.lld.im.service.user.model.UserStatusChangeNotifyContent;
import org.lld.im.service.user.model.req.PullFriendOnlineStatusReq;
import org.lld.im.service.user.model.req.PullUserOnlineStatusReq;
import org.lld.im.service.user.model.req.SetUserCustomerStatusReq;
import org.lld.im.service.user.model.req.SubscribeUserOnlineStatusReq;
import org.lld.im.service.user.model.resp.UserOnlineStatusResp;
import org.lld.im.service.user.service.ImUserStatusService;
import org.lld.im.service.user.service.UserService;
import org.lld.im.service.utils.MessageProducer;
import org.lld.im.service.utils.UserSessionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @description:
 * @author: lld
 * @version: 1.0
 */
@Service
public class ImUserStatusServiceImpl implements ImUserStatusService {

    @Resource
    UserSessionUtils userSessionUtils;

    @Resource
    MessageProducer messageProducer;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    ImFriendShipService imFriendService;

    @Override
    public void processUserOnlineStatusNotify(UserStatusChangeNotifyContent content) {
        List<UserSession> userSessions = userSessionUtils.getUserSessions(content.getAppId(), content.getUserId());
        UserStatusChangeNotifyPack userStatusChangeNotifyPack = new UserStatusChangeNotifyPack();
        BeanUtils.copyProperties(content, userStatusChangeNotifyPack);
        userStatusChangeNotifyPack.setClient(userSessions);

        //发送给自己的同步端
        syncSender(userStatusChangeNotifyPack, content.getUserId(), content);
        //同步给好友和订阅了自己的人
        dispatcher(userStatusChangeNotifyPack, content.getUserId(), content.getAppId());
    }

    private void syncSender(Object pack, String userId, ClientInfo clientInfo) {
        messageProducer.sendToUserExceptClient(userId,
                UserEventCommand.USER_ONLINE_STATUS_CHANGE_NOTIFY_SYNC,
                pack, clientInfo);
    }

    private void dispatcher(Object pack, String userId, Integer appId) {
        //获取所有的好友Id
        List<String> allFriendId = imFriendService.getAllFriendId(userId, appId);
        for (String fid : allFriendId) {
            messageProducer.sendToUser(fid, UserEventCommand.USER_ONLINE_STATUS_CHANGE_NOTIFY,
                    pack, appId);
        }
        //发送给临时订阅的人
        String userKey=appId+":"+Constants.RedisConstants.subscribe+":"+userId;
        Set<Object> keys = stringRedisTemplate.opsForHash().keys(userKey);
        for(Object key:keys){
            String filed=(String) key;
            Long expire=Long.valueOf((String) stringRedisTemplate.opsForHash().get(userKey,filed));
            if(expire>0&&expire>System.currentTimeMillis()){
                messageProducer.sendToUser(filed,UserEventCommand.USER_ONLINE_STATUS_CHANGE_NOTIFY,
                        pack,appId);
            }else{
                stringRedisTemplate.opsForHash().delete(userKey,filed);
            }
        }
    }
    @Override
    public void subscribeUserOnlineStatus(SubscribeUserOnlineStatusReq req) {
        //过期时间
        Long subExpireTime=0L;
        if(req!=null&&req.getSubTime()>0){
            subExpireTime=System.currentTimeMillis()+req.getSubTime();
        }

        for(String beSubUserId:req.getSubUserId()){
            String userKey=req.getAppId()+":"+Constants.RedisConstants.subscribe+":"+beSubUserId;
            stringRedisTemplate.opsForHash().put(userKey,req.getOperator(),subExpireTime.toString());
        }
    }

    //设置自定义状态
    @Override
    public void setUserCustomerStatus(SetUserCustomerStatusReq req) {
        UserCustomStatusChangeNotifyPack userCustomStatusChangeNotifyPack = new UserCustomStatusChangeNotifyPack();
        userCustomStatusChangeNotifyPack.setCustomStatus(req.getCustomStatus());
        userCustomStatusChangeNotifyPack.setCustomText(req.getCustomText());
        userCustomStatusChangeNotifyPack.setUserId(req.getUserId());
        stringRedisTemplate.opsForValue().set(req.getAppId()
        +":"+Constants.RedisConstants.userCustomerStatus+":"+req.getUserId()
        ,JSONObject.toJSONString(userCustomStatusChangeNotifyPack));
        syncSender(userCustomStatusChangeNotifyPack,
                req.getUserId(),new ClientInfo(req.getAppId(),req.getClientType(),req.getImei()));
        dispatcher(userCustomStatusChangeNotifyPack,req.getUserId(),req.getAppId());
    }

    @Override
    public Map<String, UserOnlineStatusResp> queryFriendOnlineStatus(PullFriendOnlineStatusReq req) {
        List<String> allFriendId = imFriendService.getAllFriendId(req.getOperator(), req.getAppId());
        return getUserOnlineStatus(allFriendId,req.getAppId());
    }

    @Override
    public Map<String, UserOnlineStatusResp> queryUserOnlineStatus(PullUserOnlineStatusReq req) {
        return getUserOnlineStatus(req.getUserList(),req.getAppId());
    }

    private Map<String,UserOnlineStatusResp> getUserOnlineStatus(List<String> userId,Integer appId){
        Map<String,UserOnlineStatusResp> result=new HashMap<>(userId.size());
        for(String uid:userId){
            UserOnlineStatusResp resp = new UserOnlineStatusResp();
            List<UserSession> userSession = userSessionUtils.getUserSessions(appId, uid);
            resp.setSession(userSession);
            String userKey=appId+":"+Constants.RedisConstants.userCustomerStatus+":"+uid;
            String s = stringRedisTemplate.opsForValue().get(userKey);
            if(StringUtils.isNotBlank(s)){
                JSONObject parse = (JSONObject) JSON.parse(s);
                resp.setCustomText(parse.getString("customText"));
                resp.setCustomStatus(parse.getInteger("customStatus"));
            }
            result.put(uid,resp);
        }
        return result;
    }
}
